<template>
  <div class="erp-material">
    <el-card shadow="never">
      <template #header>
        <div class="erp-material__header">
          <span>物料管理</span>
          <div>
            <el-button type="primary" size="small" @click="openCreate">新增</el-button>
            <el-button size="small" type="danger" :disabled="multipleSelection.length===0" @click="onBatchDelete">批量删除</el-button>
            <el-button size="small" @click="onExport">导出Excel</el-button>
            <el-button size="small" @click="onExportAsync">异步导出</el-button>
            <el-popover placement="bottom" trigger="click">
              <template #reference>
                <el-button size="small">列显隐</el-button>
              </template>
              <el-checkbox-group v-model="visibleColumnKeys" style="display:flex;flex-direction:column;min-width:160px;gap:6px;">
                <el-checkbox v-for="col in allColumns" :key="col.key" :label="col.key">{{ col.label }}</el-checkbox>
              </el-checkbox-group>
            </el-popover>
            <el-switch v-model="exportSelectedOnly" inline-prompt :active-text="'按勾选导出'" :inactive-text="'按筛选导出'" style="margin-left: 8px;" />
            <span style="margin-left: 8px;">已选 {{ selectedIds.size }} 条</span>
          </div>
        </div>
      </template>
      <el-form :inline="true" class="erp-material__search" @submit.prevent>
        <el-form-item label="物料编码">
          <el-input v-model="query.materialCode" clearable placeholder="支持模糊" />
        </el-form-item>
        <el-form-item label="物料名称">
          <el-input v-model="query.materialName" clearable placeholder="支持模糊" />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="query.status" placeholder="全部" clearable>
            <el-option :value="1" label="启用" />
            <el-option :value="0" label="停用" />
          </el-select>
        </el-form-item>
        <el-form-item label="启用批次">
          <el-select v-model="query.enableBatch" placeholder="全部" clearable>
            <el-option :value="1" label="是" />
            <el-option :value="0" label="否" />
          </el-select>
        </el-form-item>
        <el-form-item label="启用序列号">
          <el-select v-model="query.enableSerial" placeholder="全部" clearable>
            <el-option :value="1" label="是" />
            <el-option :value="0" label="否" />
          </el-select>
        </el-form-item>
        <el-form-item label="创建时间">
          <el-date-picker v-model="query.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始" end-placeholder="结束" value-format="YYYY-MM-DD HH:mm:ss" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="small" @click="onSearch">查询</el-button>
          <el-button size="small" @click="onReset">重置</el-button>
        </el-form-item>
      </el-form>

<el-table ref="tableRef" v-if="list.length > 0" :data="list" size="small" style="width: 100%" @selection-change="onSelectionChange">
        <el-table-column type="selection" width="48" />
        <el-table-column v-if="isColVisible('materialCode')" prop="materialCode" label="物料编码" min-width="120" />
        <el-table-column v-if="isColVisible('materialName')" prop="materialName" label="物料名称" min-width="160" />
        <el-table-column v-if="isColVisible('uomId')" prop="uomId" label="计量单位" min-width="100" />
        <el-table-column v-if="isColVisible('enableBatchText')" prop="enableBatch" label="批次" min-width="80">
          <template #default="{ row }">
            <el-tag :type="row.enableBatch === 1 ? 'success' : 'info'">{{ row.enableBatch === 1 ? '是' : '否' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column v-if="isColVisible('enableSerialText')" prop="enableSerial" label="序列号" min-width="80">
          <template #default="{ row }">
            <el-tag :type="row.enableSerial === 1 ? 'success' : 'info'">{{ row.enableSerial === 1 ? '是' : '否' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column v-if="isColVisible('statusText')" prop="status" label="状态" min-width="80">
          <template #default="{ row }">
            <el-tag :type="row.status === 1 ? 'success' : 'info'">{{ row.status === 1 ? '启用' : '停用' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column v-if="isColVisible('barcode')" prop="barcode" label="条码" min-width="120" />
        <el-table-column v-if="isColVisible('remark')" prop="remark" label="备注" min-width="160" />
        <el-table-column v-if="isColVisible('createTime')" prop="createTime" label="创建时间" min-width="160" />
        <el-table-column label="操作" width="160">
          <template #default="{ row }">
            <el-button link type="primary" size="small" @click="openEdit(row)">编辑</el-button>
            <el-popconfirm title="确认删除该物料？" @confirm="onDelete(row)">
              <template #reference>
                <el-button link type="danger" size="small">删除</el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <el-empty v-else description="暂无数据" />

      <div class="erp-material__pagination">
        <el-pagination
          background
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          :page-sizes="[10, 20, 50, 100]"
          :page-size="pageSize"
          :current-page="pageNum"
          @size-change="onSizeChange"
          @current-change="onPageChange"
        />
      </div>
      <div style="margin-top: 8px; display: flex; gap: 8px;">
        <el-button size="small" @click="selectCurrentPage">全选当前页</el-button>
        <el-button size="small" @click="selectAllUnderFilter">全选全部（按当前筛选）</el-button>
        <el-button size="small" @click="clearSelection">清空选择</el-button>
      </div>
    </el-card>

    <el-drawer v-model="drawerVisible" :with-header="true" :title="drawerTitle" size="520px">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="96px">
        <el-form-item label="物料编码" prop="materialCode">
          <el-input v-model="form.materialCode" maxlength="64" />
        </el-form-item>
        <el-form-item label="物料名称" prop="materialName">
          <el-input v-model="form.materialName" maxlength="200" />
        </el-form-item>
        <el-form-item label="计量单位" prop="uomId">
          <el-select v-model="form.uomId" :loading="loadingUom" placeholder="请选择计量单位" style="width: 100%" clearable @visible-change="onUomSelectVisible">
            <el-option v-for="uom in uomOptions" :key="uom.uomId" :label="`${uom.uomCode} | ${uom.uomName}`" :value="String(uom.uomId)" />
          </el-select>
        </el-form-item>
        <el-form-item label="启用批次" prop="enableBatch">
          <el-switch v-model="form.enableBatch" :active-value="1" :inactive-value="0" />
        </el-form-item>
        <el-form-item label="启用序列号" prop="enableSerial">
          <el-switch v-model="form.enableSerial" :active-value="1" :inactive-value="0" />
        </el-form-item>
        <el-form-item label="条码" prop="barcode">
          <el-input v-model="form.barcode" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-select v-model="form.status" placeholder="请选择">
            <el-option :value="1" label="启用" />
            <el-option :value="0" label="停用" />
          </el-select>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" type="textarea" :rows="3" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div style="flex: 1; text-align: center">
          <el-button @click="drawerVisible = false">取消</el-button>
          <el-button type="primary" :loading="submitLoading" @click="submitForm">保存</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
  
</template>

<script setup lang="ts">
import { onMounted, reactive, ref, nextTick, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { pageMaterial, createMaterial, updateMaterial, getMaterial, deleteMaterial, deleteMaterialBatch, exportMaterial } from '@/api/erp/material'
import { ElMessage } from 'element-plus'
import { getUserPref, saveUserPref } from '@/api/erp/pref'
import { createExportJob, getExportJobStatus, downloadExportJob } from '@/api/erp/export'
import { pageUom } from '@/api/erp/uom'

interface MaterialForm {
  materialId?: string
  materialCode: string
  materialName: string
  uomId: string
  enableBatch: number
  enableSerial: number
  barcode?: string
  status: number
  remark?: string
}

const list = ref<any[]>([])
const tableRef = ref()
const selectedIds = ref<Set<string>>(new Set())
const total = ref(0)
const pageNum = ref(1)
const pageSize = ref(10)
const query = reactive<{ materialCode?: string; materialName?: string; status?: number | '' ; enableBatch?: number | '' ; enableSerial?: number | '' ; timeRange?: string[] | [] }>(
  { materialCode: '', materialName: '', status: '', enableBatch: '', enableSerial: '', timeRange: [] }
)
const exportSelectedOnly = ref(false)
const multipleSelection = ref<any[]>([])
const allColumns = [
  { key: 'materialCode', label: '物料编码' },
  { key: 'materialName', label: '物料名称' },
  { key: 'uomId', label: '计量单位ID' },
  { key: 'enableBatchText', label: '启用批次' },
  { key: 'enableSerialText', label: '启用序列号' },
  { key: 'statusText', label: '状态' },
  { key: 'barcode', label: '条码' },
  { key: 'remark', label: '备注' },
  { key: 'createTime', label: '创建时间' }
]
const visibleColumnKeys = ref<string[]>(allColumns.map(c => c.key))
const isColVisible = (key: string) => visibleColumnKeys.value.includes(key)

const drawerVisible = ref(false)
const isEdit = ref(false)
const drawerTitle = ref('新增物料')
const formRef = ref<FormInstance>()
const form = reactive<MaterialForm>({
  materialCode: '',
  materialName: '',
  uomId: '',
  enableBatch: 0,
  enableSerial: 0,
  barcode: '',
  status: 1,
  remark: ''
})
const rules: FormRules = {
  materialCode: [{ required: true, message: '请输入物料编码', trigger: 'blur' }],
  materialName: [{ required: true, message: '请输入物料名称', trigger: 'blur' }],
  uomId: [{ required: true, message: '请选择计量单位', trigger: 'change' }]
}
const submitLoading = ref(false)
const uomOptions = ref<any[]>([])
const loadingUom = ref(false)

const load = async () => {
  const res = await pageMaterial({
    pageNum: pageNum.value,
    pageSize: pageSize.value,
    materialCode: query.materialCode || undefined,
    materialName: query.materialName || undefined,
    status: query.status === '' ? undefined : Number(query.status),
    enableBatch: query.enableBatch === '' ? undefined : Number(query.enableBatch),
    enableSerial: query.enableSerial === '' ? undefined : Number(query.enableSerial),
    startTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[0] : undefined,
    endTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[1] : undefined
  })
  list.value = res?.data?.records || []
  total.value = res?.data?.total || 0
  await nextTick()
  if (tableRef.value) {
    list.value.forEach((row) => {
      const id = String(row.materialId)
      if (selectedIds.value.has(id)) {
        tableRef.value.toggleRowSelection(row, true)
      }
    })
  }
}

const onPageChange = (p: number) => {
  pageNum.value = p
  load()
}
const onSizeChange = (s: number) => {
  pageSize.value = s
  pageNum.value = 1
  load()
}

const onSearch = () => {
  pageNum.value = 1
  load()
}

const onReset = () => {
  query.materialCode = ''
  query.materialName = ''
  query.status = ''
  query.enableBatch = ''
  query.enableSerial = ''
  query.timeRange = []
  onSearch()
}

const resetForm = () => {
  form.materialId = undefined
  form.materialCode = ''
  form.materialName = ''
  form.uomId = ''
  uomOptions.value = []
  form.enableBatch = 0
  form.enableSerial = 0
  form.barcode = ''
  form.status = 1
  form.remark = ''
}

const openCreate = () => {
  isEdit.value = false
  drawerTitle.value = '新增物料'
  resetForm()
  drawerVisible.value = true
}

const openEdit = async (row: any) => {
  isEdit.value = true
  drawerTitle.value = '编辑物料'
  const res = await getMaterial(String(row.materialId))
  const data = res?.data || {}
  form.materialId = String(data.materialId)
  form.materialCode = data.materialCode || ''
  form.materialName = data.materialName || ''
  form.uomId = String(data.uomId || '')
  form.enableBatch = Number(data.enableBatch || 0)
  form.enableSerial = Number(data.enableSerial || 0)
  form.barcode = data.barcode || ''
  form.status = Number(data.status ?? 1)
  form.remark = data.remark || ''
  // 编辑时，如果 uomId 存在，确保 UOM 选项包含该单位
  if (form.uomId && !uomOptions.value.find((u: any) => String(u.uomId) === form.uomId)) {
    await remoteUom()
  }
  drawerVisible.value = true
}

const submitForm = () => {
  if (!formRef.value) return
  formRef.value.validate(async (valid) => {
    if (!valid) return
    submitLoading.value = true
    try {
      if (isEdit.value && form.materialId) {
        await updateMaterial(String(form.materialId), {
          materialCode: form.materialCode,
          materialName: form.materialName,
          uomId: String(form.uomId),
          enableBatch: form.enableBatch,
          enableSerial: form.enableSerial,
          barcode: form.barcode,
          status: form.status,
          remark: form.remark
        })
      } else {
        await createMaterial({
          materialCode: form.materialCode,
          materialName: form.materialName,
          uomId: String(form.uomId),
          enableBatch: form.enableBatch,
          enableSerial: form.enableSerial,
          barcode: form.barcode,
          status: form.status,
          remark: form.remark
        })
      }
      drawerVisible.value = false
      await load()
    } finally {
      submitLoading.value = false
    }
  })
}

const onDelete = async (row: any) => {
  await deleteMaterial(String(row.materialId))
  selectedIds.value.delete(String(row.materialId))
  await load()
}

const onSelectionChange = (rows: any[]) => {
  multipleSelection.value = rows
  // 缓存跨页选中
  const currentIds = new Set(rows.map((r) => String(r.materialId)))
  list.value.forEach((r) => selectedIds.value.delete(String(r.materialId)))
  currentIds.forEach((id) => selectedIds.value.add(id))
}

const onBatchDelete = async () => {
  if (multipleSelection.value.length === 0) return
  const ids = multipleSelection.value.map(it => String(it.materialId))
  await deleteMaterialBatch(ids)
  ids.forEach((id) => selectedIds.value.delete(id))
  await load()
}

const remoteUom = async () => {
  if (uomOptions.value.length > 0) return // 已加载过，不再重复加载
  loadingUom.value = true
  try {
    const res = await pageUom({ pageNum: 1, pageSize: 100 })
    uomOptions.value = res?.data?.records || []
  } finally {
    loadingUom.value = false
  }
}

const onUomSelectVisible = (visible: boolean) => {
  if (visible && uomOptions.value.length === 0) {
    remoteUom()
  }
}

// 打开抽屉时加载 UOM 列表
watch(drawerVisible, (visible) => {
  if (visible) {
    remoteUom()
  }
})

const onExport = async () => {
  const params = {
    materialCode: query.materialCode || undefined,
    materialName: query.materialName || undefined,
    status: query.status === '' ? undefined : Number(query.status),
    enableBatch: query.enableBatch === '' ? undefined : Number(query.enableBatch),
    enableSerial: query.enableSerial === '' ? undefined : Number(query.enableSerial),
    startTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[0] : undefined,
    endTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[1] : undefined,
    ids: exportSelectedOnly.value && selectedIds.value.size > 0 ? Array.from(selectedIds.value) : undefined,
    columns: visibleColumnKeys.value
  }
  const res = await exportMaterial(params)
  const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
  const url = window.URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = '物料列表.xlsx'
  a.click()
  window.URL.revokeObjectURL(url)
  ElMessage.success('导出成功')
}

// 全选/清空
const selectCurrentPage = async () => {
  if (!tableRef.value) return
  list.value.forEach((row) => {
    const id = String(row.materialId)
    selectedIds.value.add(id)
    tableRef.value.toggleRowSelection(row, true)
  })
}
import { getMaterialIds } from '@/api/erp/material'
const selectAllUnderFilter = async () => {
  exportSelectedOnly.value = true
  const params = {
    materialCode: query.materialCode || undefined,
    materialName: query.materialName || undefined,
    status: query.status === '' ? undefined : Number(query.status),
    enableBatch: query.enableBatch === '' ? undefined : Number(query.enableBatch),
    enableSerial: query.enableSerial === '' ? undefined : Number(query.enableSerial),
    startTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[0] : undefined,
    endTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[1] : undefined
  }
  const res = await getMaterialIds(params)
  const ids: string[] = res?.data || []
  selectedIds.value = new Set(ids)
}
const clearSelection = () => {
  selectedIds.value.clear()
  if (tableRef.value) tableRef.value.clearSelection()
}

const onExportAsync = async () => {
  const params = {
    materialCode: query.materialCode || undefined,
    materialName: query.materialName || undefined,
    status: query.status === '' ? undefined : Number(query.status),
    enableBatch: query.enableBatch === '' ? undefined : Number(query.enableBatch),
    enableSerial: query.enableSerial === '' ? undefined : Number(query.enableSerial),
    startTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[0] : undefined,
    endTime: Array.isArray(query.timeRange) && query.timeRange.length === 2 ? query.timeRange[1] : undefined,
    ids: exportSelectedOnly.value && selectedIds.value.size > 0 ? Array.from(selectedIds.value) : undefined,
    columns: visibleColumnKeys.value
  }
  const resp = await createExportJob('material', params)
  const jobId = resp?.data
  if (!jobId) return
  ElMessage.success('导出任务已创建，开始处理...')
  const timer = setInterval(async () => {
    const s = await getExportJobStatus(jobId)
    const { status } = s?.data || {}
    if (status === 'DONE') {
      clearInterval(timer)
      const blob = await downloadExportJob(jobId)
      const url = window.URL.createObjectURL(new Blob([blob]))
      const a = document.createElement('a')
      a.href = url
      a.download = '物料列表.xlsx'
      a.click()
      window.URL.revokeObjectURL(url)
      ElMessage.success('导出完成')
    } else if (status === 'FAILED') {
      clearInterval(timer)
      ElMessage.error('导出失败')
    }
  }, 1200)
}

onMounted(async () => {
  // 加载列偏好
  try {
    const resp = await getUserPref('erp', 'material.columns')
    const stored = resp?.data
    if (stored) {
      // 安全解析 JSON：如果已经是对象，直接使用；如果是字符串，尝试解析
      let arr = null
      if (typeof stored === 'string') {
        try {
          const trimmed = stored.trim()
          if (trimmed.startsWith('[') || trimmed.startsWith('{')) {
            arr = JSON.parse(stored)
          }
        } catch (e) {
          console.warn('Failed to parse user preference:', e)
        }
      } else if (Array.isArray(stored)) {
        arr = stored
      }
      if (Array.isArray(arr)) visibleColumnKeys.value = arr
    }
  } catch (e) {
    console.warn('Failed to load user preference:', e)
  }
  await load()
})

watch(() => visibleColumnKeys.value, (val) => {
  // 保存列偏好
  saveUserPref('erp', 'material.columns', val)
}, { deep: true })
</script>

<style scoped lang="scss">
.erp-material {
  &__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  &__pagination {
    margin-top: 12px;
    display: flex;
    justify-content: flex-end;
  }
}
</style>


